package org.wk.account.service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.wk.account.dao.SubAccountDao;
import org.wk.account.dao.ling.SubAccountLingDao;
import org.wk.account.dao.ling.SubAccountLingFromZaiBillDao;
import org.wk.account.dao.ling.SubAccountLingSeqDao;
import org.wk.account.dao.yuan.SubAccountYuanDao;
import org.wk.account.dao.yuan.SubAccountYuanFromZaiBillDao;
import org.wk.account.dao.yuan.SubAccountYuanSeqDao;
import org.wk.account.dao.zai.*;
import org.wk.account.dao.zhong.*;
import org.wk.account.domain.SubAccount;
import org.wk.account.domain.ling.*;
import org.wk.account.domain.zai.*;
import org.wk.account.domain.zhong.*;
import org.wk.account.enums.*;
import org.wk.account.view.ConfigVo;
import org.wk.core.common.exception.ExceptionCode;
import org.wk.core.common.exception.GeneralExceptionCode;
import org.wk.core.common.view.ResponseVo;
import org.wk.core.db.tool.WebUtils;
import org.wk.account.dao.bao.SubAccountBaoDao;
import org.wk.account.dao.bao.SubAccountBaoReceiveOthersBillDao;
import org.wk.account.dao.bao.SubAccountBaoSeqDao;
import org.wk.account.dao.zai.SubAccountZaiDao;
import org.wk.account.dao.zai.SubAccountZaiPresentOthersBillDao;
import org.wk.account.dao.zai.SubAccountZaiSeqDao;
import org.wk.account.domain.bao.SubAccountBao;
import org.wk.account.domain.bao.SubAccountBaoReceiveOthersBill;
import org.wk.account.domain.bao.SubAccountBaoSeq;
import org.wk.account.domain.yuan.SubAccountYuan;
import org.wk.account.domain.yuan.SubAccountYuanFromZaiBill;
import org.wk.account.domain.yuan.SubAccountYuanSeq;
import org.wk.account.domain.zai.SubAccountZai;
import org.wk.account.domain.zai.SubAccountZaiPresentOthersBill;
import org.wk.account.domain.zai.SubAccountZaiSeq;
import org.wk.account.domain.zhong.SubAccountZhong;
import org.wk.account.domain.zhong.SubAccountZhongSeq;
import org.wk.core.web.exception.GeneralException;
import org.wk.user.dao.UserDao;
import org.wk.user.domain.User;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName SubAccountZaiServiceImpl
 * @Description 鲸仔业务层处理操作
 * @Author ZhaoPing'an
 * @Date 2018/5/18 11:17
 */
@Service
public class SubAccountZaiServiceImpl implements SubAccountZaiService{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SubAccountDao subAccountDao;
    @Autowired
    private SubAccountZaiDao subAccountZaiDao;
    @Autowired
    private SubAccountLingDao subAccountLingDao;
    @Autowired
    private SubAccountYuanDao subAccountYuanDao;
    @Autowired
    private SubAccountZhongDao subAccountZhongDao;
    @Autowired
    private SubAccountLingSeqDao subAccountLingSeqDao;
    @Autowired
    private SubAccountZaiSeqDao subAccountZaiSeqDao;
    @Autowired
    private SubAccountYuanSeqDao subAccountYuanSeqDao;
    @Autowired
    private SubAccountZhongSeqDao subAccountZhongSeqDao;
    @Autowired
    private SubAccountZhongFromZaiBillDao subAccountZhongFromZaiBillDao;
    @Autowired
    private SubAccountZaiToYuanBillDao subAccountZaiToYuanBillDao;
    @Autowired
    private SubAccountLingFromZaiBillDao subAccountLingFromZaiBillDao;
    @Autowired
    private SubAccountYuanFromZaiBillDao subAccountYuanFromZaiBillDao;
    @Autowired
    private SubAccountZaiToZhongBillDao subAccountZaiToZhongBillDao;
    @Autowired
    private SubAccountZaiExchangeCNYBillDao subAccountZaiExchangeCNYBillDao;
    @Autowired
    private SubAccountZaiPresentOthersBillDao subAccountZaiPresentOthersBillDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private SubAccountBaoDao subAccountBaoDao;
    @Autowired
    private SubAccountBaoSeqDao subAccountBaoSeqDao;
    @Autowired
    private SubAccountBaoReceiveOthersBillDao subAccountBaoReceiveOthersBillDao;
    @Autowired
    private SubAccountZaiAdminUpdateBillDao subAccountZaiAdminUpdateBillDao;

    @Autowired
    private ConfigService configService;


    /**
     * @Description 鲸仔兑换鲸灵、鲸种、鲸源
     * @Param [targetAccountType, jsonObject]
     * @author ZhaoPing'an
     * @Date 2018/5/18 11:31
     */
    @Transactional
    @Override
    public ResponseVo jingzaiExchangeOthers(String targetAccountType, JSONObject jsonObject) {

        int quantity = jsonObject.getIntValue("quantity");
        if (quantity < 100||quantity%100!=0){
            return new ResponseVo(ResponseCode.COMPLETE_DATA);
        }
        String userId = WebUtils.getUser().getId();
        SubAccountZai subAccountZai = subAccountZaiDao.findByUserId(userId);
        BigDecimal preAmount = subAccountZai.getAmount();
        // 鲸仔总数与当前兑换数量校验
        if (preAmount.compareTo(new BigDecimal(quantity))<0){
            return new ResponseVo(ResponseCode.AMOUNT_DATA_ERROR);
        }
        ResponseVo result = null;
        // 鲸仔兑换精灵
        if (targetAccountType.equals(AccountType.JING_LING.getCode())){
            result = jingzaiExchangeJingling(quantity,userId);
            return result;
        }
        // 鲸仔兑换精种
        if (targetAccountType.equals(AccountType.JING_ZHONG.getCode())){
            result = jingzaiExchangeJingZhong(quantity,userId);
            return result;
        }
        // 鲸仔兑换精源
        if (targetAccountType.equals(AccountType.JING_YUAN.getCode())){
            result = jingzaiExchangeJingYuan(quantity,userId);
            return result;
        }
//        JSONObject json = new JSONObject();
//        json.put("date",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
        result = ResponseVo.error();
        return result;
    }


    /**
     * @Description 鲸仔兑换鲸灵
     * @Param [quantity, userId, zaiChangeType, seqFlag]
     * @author ZhaoPing'an
     * @Date 2018/5/18 17:21
     */
    public ResponseVo jingzaiExchangeJingling(int quantity,String userId){
        ConfigVo configVo = configService.selectByCode(TransferConfig.zai_to_ling.getCode());
        if (configVo==null || Strings.isNullOrEmpty(configVo.getConfigValue())) {
            throw new GeneralException(ExceptionCode.ex_system);
        }

        // 手续费百分比
        BigDecimal percentage = new BigDecimal(configVo.getConfigValue());
        if (percentage.compareTo(new BigDecimal(0))<0) {
            return ResponseVo.error("暂停兑换功能");
        }

        // 保存鲸仔转精灵记录
        SubAccountZaiToLingBill subAccountZaiToLingBill = new SubAccountZaiToLingBill();
        subAccountZaiToLingBill.setAmount(new BigDecimal(quantity));
        subAccountZaiToLingBill.setUserId(userId);
        subAccountZaiExchangeCNYBillDao.save(subAccountZaiToLingBill);
        // 鲸仔操作
        boolean zaiResult = jingzaiHandle(quantity,userId,ZaiChangeType.TO_LING,SeqFlag.EXPEND);
        if (zaiResult){
            //更新鲸灵账户信息
            SubAccountLing subAccountLing = subAccountLingDao.findByUserId(userId);
            subAccountLing = subAccountLing==null?new SubAccountLing():subAccountLing;
            BigDecimal nowAmount = subAccountLing.getAmount();
            BigDecimal exchangeAmount = new BigDecimal(quantity).multiply(new BigDecimal(1).subtract(percentage));
            BigDecimal exchangeAfterAmount = nowAmount.add(exchangeAmount);
            subAccountLing.setUserId(userId);
            subAccountLing.setAmount(exchangeAfterAmount);
            subAccountLingDao.saveOrUpdate(subAccountLing);
            // 鲸灵来账业务处理
            SubAccountLingFromZaiBill subAccountLingFromZaiBill = new SubAccountLingFromZaiBill();
            subAccountLingFromZaiBill.setAmount(exchangeAmount);
            subAccountLingFromZaiBill.setUserId(userId);
            subAccountLingFromZaiBillDao.save(subAccountLingFromZaiBill);
            //保存鲸灵账户变动记录
            SubAccountLingSeq subAccountLingSeq = new SubAccountLingSeq();
            subAccountLingSeq.setUserId(userId);
            subAccountLingSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
            subAccountLingSeq.setSeqFlagName(SeqFlag.INCOME.getName());
            subAccountLingSeq.setChangeTypeCode(ZhongChangeType.FROM_ZAI.getCode());
            subAccountLingSeq.setChangeTypeName(ZhongChangeType.FROM_ZAI.getName());
            subAccountLingSeq.setPreAmount(nowAmount);
            subAccountLingSeq.setAmount(exchangeAfterAmount);
            subAccountLingSeq.setChangeAmount(exchangeAmount);
            subAccountLingSeqDao.save(subAccountLingSeq);
            //保存用户账户中鲸灵账户信息
            SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId,AccountType.JING_LING.getCode());
            subAccount.setAmount(subAccount.getAmount().add(exchangeAmount));
            subAccountDao.update(subAccount);
        }
        return ResponseVo.success();
    }

    /**
     * @Description 鲸仔兑换鲸种
     * @Param [quantity, userId, zaiChangeType, seqFlag]
     * @author ZhaoPing'an
     * @Date 2018/5/18 17:27
     */
    public ResponseVo jingzaiExchangeJingZhong(int quantity,String userId) {
        // 兑换鲸种规则100：1
        int exchange_rule = 100;
        ResponseVo result = new ResponseVo();
        // 鲸仔操作
        SubAccountZaiToZhongBill subAccountZaiToZhongBill = new SubAccountZaiToZhongBill();
        subAccountZaiToZhongBill.setAmount(new BigDecimal(quantity));
        subAccountZaiToZhongBill.setUserId(userId);
        subAccountZaiToZhongBillDao.save(subAccountZaiToZhongBill);
        boolean zaiResult = jingzaiHandle(quantity,userId,ZaiChangeType.TO_ZHONG,SeqFlag.EXPEND);
        // 鲸种操作
        if (zaiResult){
            //保存鲸源种账户记录
            SubAccountZhong subAccountZhong = subAccountZhongDao.findByUserId(userId);
            int nowAmount = subAccountZhong.getAmount();
            int exchangeAmount = quantity/exchange_rule;
            int exchangeAfterAmount = nowAmount+exchangeAmount;
            subAccountZhong.setUserId(userId);
            subAccountZhong.setAmount(exchangeAfterAmount);
            subAccountZhongDao.saveOrUpdate(subAccountZhong);
            // 鲸种来账业务处理
            SubAccountZhongFromZaiBill subAccountZhongFromZaiBill = new SubAccountZhongFromZaiBill();
            subAccountZhongFromZaiBill.setAmount(exchangeAmount);
            subAccountZhongFromZaiBill.setUserId(userId);
            subAccountZhongFromZaiBillDao.save(subAccountZhongFromZaiBill);
            //保存鲸种账户变动记录
            SubAccountZhongSeq subAccountZhongSeq = new SubAccountZhongSeq();
            subAccountZhongSeq.setUserId(userId);
            subAccountZhongSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
            subAccountZhongSeq.setSeqFlagName(SeqFlag.INCOME.getName());
            subAccountZhongSeq.setChangeTypeCode(ZhongChangeType.FROM_ZAI.getCode());
            subAccountZhongSeq.setChangeTypeName(ZhongChangeType.FROM_ZAI.getName());
            subAccountZhongSeq.setPreAmount(nowAmount);
            subAccountZhongSeq.setAmount(exchangeAfterAmount);
            subAccountZhongSeq.setChangeAmount(exchangeAmount);
            subAccountZhongSeqDao.save(subAccountZhongSeq);
            //保存用户账户中鲸种账户记录
            SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId,AccountType.JING_ZHONG.getCode());
            subAccount.setAmount(new BigDecimal(exchangeAfterAmount));
            subAccountDao.update(subAccount);
        }
        return ResponseVo.success();
    }

    /**
     * @Description 鲸仔转鲸源
     * @Param [quantity, userId, zaiChangeType, seqFlag]
     * @author ZhaoPing'an
     * @Date 2018/5/18 17:21
     */
    private ResponseVo jingzaiExchangeJingYuan(int quantity,String userId) {

        ConfigVo configVo = configService.selectByCode(TransferConfig.zai_to_yuan.getCode());
        if (configVo==null || Strings.isNullOrEmpty(configVo.getConfigValue())) {
            throw new GeneralException(ExceptionCode.ex_system);
        }

        BigDecimal percentage = new BigDecimal(configVo.getConfigValue());
        if (percentage.compareTo(new BigDecimal(0))<=0) {
            return ResponseVo.error("暂停兑换功能");
        }

        // 鲸仔操作
        SubAccountZaiToYuanBill subAccountZaiToYuanBill = new SubAccountZaiToYuanBill();
        subAccountZaiToYuanBill.setAmount(new BigDecimal(quantity));
        subAccountZaiToYuanBill.setUserId(userId);
        subAccountZaiToYuanBillDao.save(subAccountZaiToYuanBill);
        boolean zaiResult = jingzaiHandle(quantity,userId,ZaiChangeType.TO_YUAN,SeqFlag.EXPEND);
        // 鲸源操作
        if (zaiResult){
            //保存鲸源账户
            SubAccountYuan subAccountYuan = subAccountYuanDao.findByUserId(userId);
            BigDecimal nowAmount = subAccountYuan.getAmount();
            BigDecimal exchangeAmount = percentage.multiply(new BigDecimal(quantity));
            BigDecimal exchangeAfterAmount = nowAmount.add(exchangeAmount);
            subAccountYuan.setUserId(userId);
            subAccountYuan.setAmount(exchangeAfterAmount);
            subAccountYuanDao.saveOrUpdate(subAccountYuan);
            // 保存鲸源入账业务
            SubAccountYuanFromZaiBill subAccountYuanFromZaiBill = new SubAccountYuanFromZaiBill();
            subAccountYuanFromZaiBill.setAmount(exchangeAmount);
            subAccountYuanFromZaiBill.setUserId(userId);
            subAccountYuanFromZaiBillDao.save(subAccountYuanFromZaiBill);
            //保存鲸源账户变动记录
            SubAccountYuanSeq subAccountYuanSeq = new SubAccountYuanSeq();
            subAccountYuanSeq.setUserId(userId);
            subAccountYuanSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
            subAccountYuanSeq.setSeqFlagName(SeqFlag.INCOME.getName());
            subAccountYuanSeq.setChangeTypeCode(YuanChangeType.FROM_ZAI.getCode());
            subAccountYuanSeq.setChangeTypeName(YuanChangeType.FROM_ZAI.getName());
            subAccountYuanSeq.setPreAmount(nowAmount);
            subAccountYuanSeq.setAmount(exchangeAfterAmount);
            subAccountYuanSeq.setChangeAmount(exchangeAmount);
            subAccountYuanSeqDao.save(subAccountYuanSeq);
            //保存用户账户中鲸灵账户记录
            SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId,AccountType.JING_YUAN.getCode());
            subAccount.setAmount(subAccount.getAmount().add(exchangeAmount));
            subAccountDao.update(subAccount);
        }
        return ResponseVo.success();
    }

    /**
     * @Description 鲸仔操作
     * @Param ququantity 数量
     * @Param userId 兑换人
     * @author ZhaoPing'an
     * @Date 2018/5/18 10:57
     */
    public boolean jingzaiHandle(int quantity,String userId,ZaiChangeType zaiChangeType,SeqFlag seqFlag) {
        //保存鲸仔账户记录
        SubAccountZai subAccountZai = subAccountZaiDao.findByUserId(userId);
        BigDecimal preAmount = subAccountZai.getAmount();
        subAccountZai.setUserId(userId);
        subAccountZai.setAmount(preAmount.subtract(new BigDecimal(quantity)));
        subAccountZaiDao.saveOrUpdate(subAccountZai);
        //保存鲸仔账户变动记录
        SubAccountZaiSeq subAccountZaiSeq = new SubAccountZaiSeq();
        subAccountZaiSeq.setUserId(userId);
        subAccountZaiSeq.setSeqFlagCode(seqFlag.getCode());
        subAccountZaiSeq.setSeqFlagName(seqFlag.getName());
        subAccountZaiSeq.setChangeTypeCode(zaiChangeType.getCode());
        subAccountZaiSeq.setChangeTypeName(zaiChangeType.getName());
        subAccountZaiSeq.setPreAmount(preAmount);
        subAccountZaiSeq.setAmount(subAccountZai.getAmount());
        subAccountZaiSeq.setChangeAmount(new BigDecimal(quantity));
        subAccountZaiSeqDao.save(subAccountZaiSeq);
        //保存用户账户中鲸仔账户记录
        SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_ZAI.getCode());
        subAccount.setAmount(subAccount.getAmount().subtract(new BigDecimal(quantity)));
        subAccountDao.update(subAccount);
        return true;
    }


    @Override
    public Page<SubAccountZaiSeq> findSeqByCriteria(Integer page, Integer size, SubAccountZaiSeq subAccountZaiSeq) {
        Sort sort = Sort.by(Sort.Direction.DESC,"createTime");
        Page<SubAccountZaiSeq> zaiSeqPage = subAccountZaiSeqDao.findAll(new Specification<SubAccountZaiSeq>() {
            @Override
            public Predicate toPredicate(Root<SubAccountZaiSeq> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                if(null!=subAccountZaiSeq.getUserId()&&!"".equals(subAccountZaiSeq.getUserId())){
                    list.add(criteriaBuilder.equal(root.get("userId").as(String.class), subAccountZaiSeq.getUserId()));
                }
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            }
        }, PageRequest.of(page,size,sort));
        return zaiSeqPage;
    }

    /**
     * 鲸仔转增他人
     * @author TangShenShen
     * @date 2018/5/29 11:50
     */
    @Transactional
    @Override
    public ResponseVo presentOthers(JSONObject jsonObject) {
        logger.info("鲸仔转增他人");
        int quantity = jsonObject.getIntValue("quantity");
        //转赠鲸仔数量必须为100整数倍
        if (quantity<=0 || quantity%100!=0 ){
            return ResponseVo.error("金额必须是100的整数倍。");
        }
        // 转赠人userId
        SubAccountZai subAccountZai = subAccountZaiDao.findByUserId(WebUtils.getUser().getId());
        BigDecimal preAmount = subAccountZai.getAmount();
        // 鲸仔总数与当前转赠数量校验
        if (preAmount.compareTo(new BigDecimal(quantity))<0){
            return new ResponseVo(ResponseCode.AMOUNT_DATA_ERROR);
        }

        String mobileNumber = jsonObject.getString("mobile_number");

        User user = userDao.findByMobileNumber(mobileNumber);
        if (user==null){
            return new ResponseVo(ResponseCode.ACCOUNTS_UN_EXIST);
        }

        String userId = user.getId();  //被转增人id

        SubAccountZaiPresentOthersBill subAccountZaiPresentOthersBill = new SubAccountZaiPresentOthersBill();
        subAccountZaiPresentOthersBill.setAmount(new BigDecimal(quantity));
        subAccountZaiPresentOthersBill.setUserId(WebUtils.getUser().getId());
        subAccountZaiPresentOthersBill.setPresentUserId(userId);
        subAccountZaiPresentOthersBillDao.save(subAccountZaiPresentOthersBill);
        // 鲸仔数量变动处理
        presentHander(WebUtils.getUser().getId(),quantity,SeqFlag.EXPEND ,ZaiChangeType.PRESENT_OTHERS);
        // 自己鲸源数量处理
        addSelfYuanHandler(WebUtils.getUser().getId(),quantity);
        // 被赠予人的处理逻辑
        receiveHandler(userId,quantity,SeqFlag.INCOME,BaoChangeType.RECEIVE_OTHERS);

        return ResponseVo.success();
    }

    @Override
    public void updateZaiAccount(BigDecimal zai, String userId) {
        SubAccountZai subAccountZai = subAccountZaiDao.findByUserId(userId);
        SubAccountZaiSeq subAccountZaiSeq = new SubAccountZaiSeq();
        BigDecimal amount = subAccountZai.getAmount();
        BigDecimal changeAmount = new BigDecimal(0);
        int num = zai.compareTo(amount);
        if (num < 0){
            changeAmount = amount.subtract(zai);
            subAccountZaiSeq.setSeqFlagCode(SeqFlag.EXPEND.getCode());
            subAccountZaiSeq.setSeqFlagName(SeqFlag.EXPEND.getName());
        }
        if (num > 0){
            changeAmount = zai.subtract(amount);
            subAccountZaiSeq.setSeqFlagCode(SeqFlag.INCOME.getCode());
            subAccountZaiSeq.setSeqFlagName(SeqFlag.INCOME.getName());
        }
        if (num!=0 && zai.compareTo(new BigDecimal(0))>=0){
            SubAccountZaiAdminUpdateBill adminUpdateBill = new SubAccountZaiAdminUpdateBill();
            adminUpdateBill.setAmount(changeAmount);
            adminUpdateBill.setUserId(userId);
            subAccountZaiAdminUpdateBillDao.save(adminUpdateBill);
            subAccountZai.setAmount(zai);
            subAccountZai.setUserId(userId);
            subAccountZaiDao.saveOrUpdate(subAccountZai);
            subAccountZaiSeq.setUserId(userId);
            subAccountZaiSeq.setChangeTypeCode(BaoChangeType.ADMIN_UPDATE.getCode());
            subAccountZaiSeq.setChangeTypeName(BaoChangeType.ADMIN_UPDATE.getName());
            subAccountZaiSeq.setPreAmount(amount);
            subAccountZaiSeq.setAmount(zai);
            subAccountZaiSeq.setChangeAmount(changeAmount);
            subAccountZaiSeqDao.save(subAccountZaiSeq);
            SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_ZAI.getCode());
            subAccount.setAmount(zai);
            subAccountDao.update(subAccount);
        }
    }

    @Override
    public Page<SubAccountZaiSeq> findSeqByUserIds(int pageNum, int pageSize, List<String> userIds) {
        Sort sort = Sort.by(Sort.Direction.DESC,"createTime");
        Page<SubAccountZaiSeq> zaiSeqPage = subAccountZaiSeqDao.findAll(new Specification<SubAccountZaiSeq>() {
            @Override
            public Predicate toPredicate(Root<SubAccountZaiSeq> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                if(!userIds.isEmpty()){
                    CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("userId"));
                    for (String userId:userIds){
                        in.value(userId);
                    }
                    list.add(in);
                }
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            }
        }, PageRequest.of(pageNum,pageSize,sort));
        return zaiSeqPage;
    }



    //

    /**
     * 鲸仔转赠他人时，增加自己的鲸源
     * @param userId  用户ID
     * @param quantity 转赠鲸仔数量
     * @return
     */
    private boolean addSelfYuanHandler(String userId, int quantity) {
        ConfigVo configVo = configService.selectByCode(TransferConfig.zai_present_others_donate.getCode());
        if (configVo==null || Strings.isNullOrEmpty(configVo.getConfigValue())) {
            logger.info("未设置注册奖励");
            return true;
        }

        BigDecimal percentage = new BigDecimal(configVo.getConfigValue());
        if (percentage.compareTo(new BigDecimal(0))<=0) {
            return true;
        }

        SeqFlag income = SeqFlag.INCOME;
        YuanChangeType presentOther = YuanChangeType.PRESENT_OTHER;

        BigDecimal incomeAmout = new BigDecimal(quantity).multiply(percentage);

        SubAccountYuanFromZaiBill subAccountYuanFromZaiBill = new SubAccountYuanFromZaiBill();
        subAccountYuanFromZaiBill.setUserId(userId);
        subAccountYuanFromZaiBill.setAmount(incomeAmout);
        subAccountYuanFromZaiBillDao.save(subAccountYuanFromZaiBill);

        SubAccountYuan subAccountYuan = subAccountYuanDao.findByUserId(userId);
        subAccountYuan = subAccountYuan==null?new SubAccountYuan():subAccountYuan;
        BigDecimal preAmount = subAccountYuan.getAmount();
        subAccountYuan.setAmount(preAmount.add(incomeAmout));
        subAccountYuan.setUserId(userId);
        subAccountYuanDao.saveOrUpdate(subAccountYuan);

        SubAccountYuanSeq subAccountYuanSeq = new SubAccountYuanSeq();
        subAccountYuanSeq.setUserId(userId);
        subAccountYuanSeq.setSeqFlagCode(income.getCode());
        subAccountYuanSeq.setSeqFlagName(income.getName());
        subAccountYuanSeq.setChangeTypeCode(presentOther.getCode());
        subAccountYuanSeq.setChangeTypeName(presentOther.getName());
        subAccountYuanSeq.setPreAmount(preAmount);
        subAccountYuanSeq.setAmount(subAccountYuan.getAmount());
        subAccountYuanSeq.setChangeAmount(incomeAmout);
        subAccountYuanSeqDao.save(subAccountYuanSeq);

        SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_YUAN.getCode());
        subAccount.setAmount(subAccountYuan.getAmount());
        subAccountDao.update(subAccount);

        return true;
    }

    // 处理转赠人的逻辑
    private boolean presentHander(String id, int quantity, SeqFlag expend, ZaiChangeType presentOthers) {

        SubAccountZai subAccountZai = subAccountZaiDao.findByUserId(id);
        subAccountZai = subAccountZai==null?new SubAccountZai():subAccountZai;
        BigDecimal preAmount = subAccountZai.getAmount();
        subAccountZai.setAmount(preAmount.subtract(new BigDecimal(quantity))); //减去
        subAccountZai.setUserId(id);
        subAccountZaiDao.saveOrUpdate(subAccountZai);

        SubAccountZaiSeq subAccountZaiSeq = new SubAccountZaiSeq();
        subAccountZaiSeq.setUserId(id);
        subAccountZaiSeq.setSeqFlagCode(expend.getCode());
        subAccountZaiSeq.setSeqFlagName(expend.getName());
        subAccountZaiSeq.setChangeTypeCode(presentOthers.getCode());
        subAccountZaiSeq.setChangeTypeName(presentOthers.getName());
        subAccountZaiSeq.setPreAmount(preAmount);
        subAccountZaiSeq.setAmount(subAccountZai.getAmount());
        subAccountZaiSeq.setChangeAmount(new BigDecimal(quantity));
        subAccountZaiSeqDao.save(subAccountZaiSeq);

        SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(id, AccountType.JING_ZAI.getCode());
        subAccount.setAmount(subAccountZai.getAmount());
        subAccountDao.update(subAccount);
        return true;
    }

    // 处理被转增人的逻辑
    private boolean receiveHandler(String userId, int quantity, SeqFlag income, BaoChangeType receiveOthers) {

        // 插入接受转赠表
        SubAccountBaoReceiveOthersBill subAccountBaoReceiveOthersBill = new SubAccountBaoReceiveOthersBill();
        subAccountBaoReceiveOthersBill.setUserId(userId);
        subAccountBaoReceiveOthersBill.setReceiveUserId(WebUtils.getUser().getId());
        subAccountBaoReceiveOthersBill.setAmount(new BigDecimal(quantity));
        subAccountBaoReceiveOthersBillDao.save(subAccountBaoReceiveOthersBill);

        SubAccountBao subAccountBao = subAccountBaoDao.findByUserId(userId);
        subAccountBao = subAccountBao==null?new SubAccountBao():subAccountBao;
        BigDecimal preAmount = subAccountBao.getAmount()==null?new BigDecimal(0):subAccountBao.getAmount();
        subAccountBao.setAmount(preAmount.add(new BigDecimal(quantity)));
        subAccountBao.setUserId(userId);
        subAccountBaoDao.saveOrUpdate(subAccountBao);

        SubAccountBaoSeq subAccountBaoSeq = new SubAccountBaoSeq();
        subAccountBaoSeq.setUserId(userId);
        subAccountBaoSeq.setSeqFlagCode(income.getCode());
        subAccountBaoSeq.setSeqFlagName(income.getName());
        subAccountBaoSeq.setChangeTypeCode(receiveOthers.getCode());
        subAccountBaoSeq.setChangeTypeName(receiveOthers.getName());
        subAccountBaoSeq.setPreAmount(preAmount);
        subAccountBaoSeq.setAmount(subAccountBao.getAmount());
        subAccountBaoSeq.setChangeAmount(new BigDecimal(quantity));
        subAccountBaoSeqDao.save(subAccountBaoSeq);

        SubAccount subAccount = subAccountDao.findByUserIdAndAccountTypeCode(userId, AccountType.JING_BAO.getCode());
        subAccount.setAmount(subAccountBao.getAmount());
        subAccountDao.update(subAccount);
        return true;
    }


}
